use anyhow::{bail, Result};
use sha1::Digest;
use sha1::Sha1;
use sha2::{Sha256, Sha512};
use std::io::Read;
use std::path::Path;
use std::{fs::File, io};
pub enum HashKind {
    MD5,
    SHA1,
    SHA256,
    SHA512,
    Invalid,
}
impl From<&str> for HashKind {
    #[inline]
    fn from(kind: &str) -> Self {
        match kind.as_bytes() {
            b"md5" => Self::MD5,
            b"sha1" => Self::SHA1,
            b"sha256" => Self::SHA256,
            b"sha512" => Self::SHA512,
            _ => Self::Invalid,
        }
    }
}
impl HashKind {
    #[inline]
    pub fn checksum<P: AsRef<Path>>(&self, file: P, hash: &str) -> Result<bool> {
        let mut file = File::open(file)?;
        let sum = match self {
            HashKind::MD5 => {
                let mut buf = Vec::new();
                file.read_to_end(&mut buf)?;
                hex::encode(md5::compute(buf).0)
            }
            HashKind::SHA1 => {
                let mut hasher = Sha1::new();
                io::copy(&mut file, &mut hasher)?;
                hex::encode(hasher.finalize())
            }
            HashKind::SHA256 => {
                let mut hasher = Sha256::new();
                io::copy(&mut file, &mut hasher)?;

                hex::encode(hasher.finalize())
            }

            HashKind::SHA512 => {
                let mut hasher = Sha512::new();
                io::copy(&mut file, &mut hasher)?;
                hex::encode(hasher.finalize())
            }
            HashKind::Invalid => {
                bail!("Invalid hash algorithm")
            }
        };
        Ok(sum == hash)
    }
}

